package com.hc.programming.interview;

import java.util.*;
import java.util.concurrent.*;

/**
 * 精灵云二面题：
 * map做一个缓存：如果存在，就返回结果；如果不存在，创建object、put，并返回结果
 * 前提：map中已有元素不能被覆盖
 *
 * @author huangchao E-mail:fengquan8866@163.com
 * @version 创建时间：2024/7/25 11:16
 */
public class Map存储单例 {

    private static Map<String, Object> map = new HashMap<>();
//    private static Map<String, Object> map = new ConcurrentHashMap<>();

    private static int count = 100 * 10000;

    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(10000, 10000, 60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(count), new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int[] arr = new int[count];
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            arr[i] = random.nextInt(count);
        }
        threadPool(arr);
//        syncRun(arr);
    }

    /**
     * 多线程同步执行
     */
    private static void syncRun(int[] arr) {
        CyclicBarrier barrier = new CyclicBarrier(count);
        System.out.println(System.currentTimeMillis() + "-开始多线程提交任务");
        for (int n : arr) {
            new Thread(() -> {
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
                get(n);
            }).start();
        }
        System.out.println(System.currentTimeMillis() + "-执行结束");
    }

    /**
     * 线程池执行
     */
    private static void threadPool(int[] arr) {
        System.out.println(System.currentTimeMillis() + "-开始多线程提交任务");
        List<Future<Object>> rst = new ArrayList<>();
        // 多线程get：如果不存在会自动put+返回
        for (int n : arr) {
            try {
                rst.add(executor.submit(() -> get(n)));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(System.currentTimeMillis() + "-任务提交完毕");
        for (Future<Object> f : rst) {
            try {
                f.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(System.currentTimeMillis() + "-执行结束");
        executor.shutdown();
    }

    private static Object get(int n) {
        String key = "key" + n;
        Object o = map.get(key);
        if (o != null) {
            return o;
        }
        synchronized (Map存储单例.class) {
            o = map.get(key);
            if (o != null) {
                return o;
            }
            o = new Object();
            map.put(key, o);
            return o;
        }
    }
}
